// file:libc/include/stdio.h
// autor:jiangxinpeng
// time:2021.8.14
// copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#ifndef _LIBC_STDIO_H
#define _LIBC_STDIO_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <types.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <sizes.h>
#include <errno.h>
#include <limits.h>
#include <sys/fifo.h>

#ifndef EOF
// indicate eof of file
#define EOF (-1)
#endif

#ifndef NULL
#define NULL (void *)0
#endif

#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

#ifndef BUFFSZ
#define BUFFSZ (4096)
#endif

#ifndef L_tmpnam
#define L_tmpname 32
#endif

    // file position type
    typedef uint64_t fpos_t;

    // state variable
    typedef struct _FILE FILE;

    typedef struct _FILE
    {
        int fd;

        size_t (*read)(FILE *, uint8_t *, size_t);
        size_t (*write)(FILE *, uint8_t *, size_t);
        fpos_t (*seek)(FILE *, fpos_t, int);
        int (*close)(FILE *);

        fifo_t *fifo_read;
        fifo_t *fifo_write;

        uint8_t *buff;
        size_t buffsize;
        int (*rwflush)(FILE *);

        fpos_t pos;
        int mode;
        int eof, err;
    } FILE;

#define stdin (__stdio_get_stdin())
#define stdout (__stdio_get_stdout())
#define stderr (__stdio_get_stderr())

// buffer set flags
#define _IONBF 2 // no buffer
#define _IOLBF 1 // line buffer
#define _IOFBF 0 // fully buffer

    int __stdio_no_flush(FILE *f);
    int __stdio_read_flush(FILE *f);
    int __stdio_write_flush(FILE *f);
    size_t __stdio_write(FILE *f, const uint8_t *buff, size_t size);
    size_t __stdio_read(FILE *f, uint8_t *buff, size_t size);

    FILE *__stdio_get_stderr();
    FILE *__stdio_get_stdout();
    FILE *__stdio_get_stdin();
    FILE *__file_alloc(int fd);

    int fflush(FILE *f);
    FILE *fopen(const char *path, const char *mode);
    int fclose(FILE *f);
    int fprintf(FILE *f, const char *fmt, ...);
    int fscanf(FILE *f, const uint8_t *fmt, ...);
    int fputc(int c, FILE *f);
    int fputs(const char *s, FILE *f);
    int fgetc(FILE *f);
    char *fgets(char *s, int n, FILE *f);
    FILE *freopen(const char *path, const char *mode, FILE *f);
    int fseek(FILE *f, fpos_t off, int whence);
    size_t fread(void *buff, size_t size, size_t count, FILE *f);
    size_t fwrite(const void *buff, size_t size, size_t count, FILE *f);
    int getc(FILE *f);
    int gets(char *str);
    int putc(int ch, FILE *f);
    int remove(const char *path);
    int putchar(const char ch);
    int puts(const char *str);

    int printf(const char *fmt, ...);
    int scanf(const char *fmt, ...);

    FILE *tmpfile();
    char *tmpnam(char *buff);
    int vfprintf(FILE *f, const char *fmt, va_list arg);
    int vsnprintf(char *buff, size_t n, const char *fmt, va_list arg);
    int vsscanf(const char *buf, const char *fmt, va_list ap);
    int sprintf(char *buff, const char *fmt, ...);
    int snprintf(char *buff, size_t n, const char *fmt, ...);
    #define vsprintf(buff,fmt,arg) vsnprintf(buff,BUFFSZ,fmt,arg)

    int setvbuf(FILE *f, char *buff, int mode, size_t size);
    void setbuf(FILE *f, char *buff);

#ifdef __cplusplus
}
#endif
#endif
